class ListNode {
  constructor(val = 0, next = null) {
    this.val = val; // 当前节点的值
    this.next = next; // 指向下一个节点的指针
  }
}

// 反转链表中指定的一段子链表，并返回反转后的头尾节点
function reverse(head, tail) {
  let prev = tail.next; // 记录翻转前尾节点的下一个节点，用于连接后续链表
  let curr = head; // 当前遍历到的节点，从头节点开始
  while (prev !== tail) {
    const next = curr.next; // 暂存当前节点的下一个节点
    curr.next = prev; // 当前节点指向前一个节点，实现反转
    prev = curr; // 更新 prev 为当前节点
    curr = next; // 更新 curr 为下一个节点，进行下一轮反转操作
  }
  return [tail, head]; // 返回反转后的头尾节点
}

// 将链表按照 k 个一组进行翻转
function reverseKGroup(head, k) {
  const dummy = new ListNode(0); // 创建虚拟头节点，方便处理边界情况
  dummy.next = head; // 虚拟头节点指向原链表的头节点
  let prev = dummy; // prev 指向待翻转链表的前一个节点
  while (head) {
    let tail = prev; // tail 指向待翻转链表的尾节点
    // 查找下一组待翻转的尾节点
    for (let i = 0; i < k; i++) {
      tail = tail.next;
      if (!tail) return dummy.next; // 如果剩余节点数量不足 k，则直接返回结果
    }
    const nextHead = tail.next; // 记录下一组待翻转链表的头节点
    [head, tail] = reverse(head, tail); // 反转当前组链表，并获取反转后的头尾节点
    prev.next = head; // 连接上一组翻转后的尾节点和当前组翻转后的头节点
    tail.next = nextHead; // 连接当前组翻转后的尾节点和下一组未翻转的头节点
    prev = tail; // 更新 prev 指针为当前组翻转后的尾节点
    head = nextHead; // 更新 head 指针为下一组待翻转的头节点，进行下一轮翻转操作
  }
  return dummy.next; // 返回整个链表的头节点
}
